import datetime
import json
import random
import re
import time
import uuid
from io import BytesIO

import requests
from django.shortcuts import redirect
from django.views import View

from user.middleware import QingJiaInfoSer
from user.tasks import putUser
from .ser import *
import jwt
from captcha.image import ImageCaptcha
from django.contrib.auth.hashers import check_password, make_password
from .tests import *
from django.http import HttpResponse
from rest_framework.views import APIView
from rest_framework.response import Response
import redis
from user.MyRedis import MyRedis

#  连接redis
from my.settings import SECRET_KEY
from user.models import User

r = redis.Redis(
    host='127.0.0.1',
    port=6379,
    password='',
    decode_responses=True
)


#  随机数函数
def random_str(num=4):
    random__str = [chr(i) for i in range(97, 123)]
    random__num = [str(i) for i in range(1, 9)]

    return ''.join(random.sample(random__num + random__str, num))


#  创建图片验证码
def make_verify_image(code_str, image_uuid=None):
    """
    创建图片验证码
    :param code_str:
    :param image_uuid:
    :return:
    """
    # 保存验证码到redis中，并设置过期时间60s
    r.set(image_uuid, code_str, 60)
    # 生成图片验证码
    img = ImageCaptcha().generate_image(code_str)
    # 图片不会永久存储，只需要在内存中存储即可
    # 把Image对象写入到IO流中
    out = BytesIO()
    img.save(out, 'jpeg')
    # 返回图片内容
    return out.getvalue()


#  返回给前端uuid,浏览器唯一标识
class UUidCrete(APIView):
    def get(self, request):
        return Response(str(uuid.uuid4()))


class GendertUUid(APIView):
    def get(self, request):
        """
        返回验证码图片
        :param request:
        :return:
        """
        #  uuid
        uuid = request.GET.get('id')

        # 生成随机数
        random_num = random_str()

        # 生成图片
        image = make_verify_image(random_num, uuid)

        # 返回图片
        return HttpResponse(image, content_type='image/jpeg')


class Refresh(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        phone = request.data.get('phone')
        # 用户输入的验证码
        crossing = request.data.get('crossing')
        print(crossing)
        # uuid
        uuid = request.data.get('uuid')
        # redis存储的验证码
        redis_uuid = str(r.get(uuid))
        print(redis_uuid)
        # 验证手机号
        user_phone = User.objects.filter(phone=phone).first()
        if user_phone:
            return Response({'msg': '手机号已被绑定,请重新输入!', 'code': 10006})

        #  验证用户名不能为空
        if username == '':
            return Response({'msg': '用户名不能为空!', 'code': 10004})

        #  正则验证手机号格式
        new_phone = re.match('^1[3-9]{1}[0-9]{9}$', phone)
        if new_phone:
            pass
        else:
            return Response({'msg': '手机号格式不符合!', 'code': 10005})

        # 与redis的验证码作比较
        if crossing == redis_uuid:

            user = User.objects.filter(username=username).first()
            #  验证用户名是否重复
            if user:
                return Response({'msg': '用户名重复,请重新输入!', 'code': 10002})
            else:
                #  注册
                User.objects.create(
                    username=username,
                    password=password,
                    phone=phone

                )

                return Response({'msg': '注册成功!', 'code': 10000})
        else:
            return Response({'msg': '验证码输入错误,请重新输入!', 'code': 10001})


class LoginUser(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')

        user = User.objects.filter(username=username, password=password).first()

        if user:

            #  实现状态保持
            payload = {
                'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=10),
                'uid': user.id,
            }
            token = jwt.encode(payload=payload, key=SECRET_KEY)
            return Response({'msg': '登录成功', 'code': 10000, 'token': token, 'uid': user.id, 'username': user.username})

        else:

            key = 'user_%s' % username
            key_black = 'user_black'

            # 只要黑名单有该用户直接封杀
            if r.get(key_black) == key:
                return Response({'msg': '您的账号已经被封禁1分钟!', 'code': 44444})
            else:
                # 判断用户是否存在
                if r.keys(key):
                    #  五分钟内出现五次以上
                    if int(r.get(key)) >= 5:
                        r.set(key, 0)  # 清除该用户次数
                        r.set(key_black, key)  # 清除同时加入黑名单
                        r.expire(key_black, 60)  # 并且设置封禁时间
                        return Response({'msg': '您的账号已经被封禁1分钟!', 'code': 44444})
                    # 小于五次次数 做累加
                    else:
                        r.incrby(key, 1)
                        return Response({'msg': '账号或密码输入错,请重新输入!', 'code': 10004})
                # 不存在则存取
                else:
                    r.set(key, 1)
                    r.expire(key, 30)
                    return Response({'msg': '账号或密码输入错,请重新输入!', 'code': 10004})


class SelectUser(APIView):
    def get(self, request):
        username = request.GET.get('username')
        if username:
            queryset = User.objects.filter(username=username)
            ser = UserSer1(queryset, many=True)
            return Response(ser.data)
        else:
            queryset = User.objects.all()
            ser = UserSer1(queryset, many=True)
            return Response(ser.data)

    def delete(self, request):
        id = request.GET.get('id')
        if id:
            User.objects.filter(id=id).delete()
            return Response({'msg': '删除成功'})
        else:
            return Response({'msg': '没有该id'})


class PutUser(APIView):
    def put(self, request):
        username = request.data.get('username')
        new_username = request.data.get('new_username', username)
        password = request.data.get('password')
        phone = request.data.get('phone')
        data = putUser(username, new_username, password, phone)
        print(data)
        return Response(data)


from user.text_queue import MyQueue
import datetime


class UpdateUser(APIView):
    def post(self, request):
        # 获取id
        uid = request.data.get('uid', None)
        # 用户名
        username = request.data.get('username', None)
        level = User.objects.get(id=uid).level
        # 入队
        myq = MyQueue()
        myq.push(uid=uid, level=level, username=username)

        myq.printf()
        return Response({'msg': '审核中请等待'})

    def get(self, request):
        myq = MyQueue()
        return Response({'data': myq.show()})

    def put(self, request):
        myq = MyQueue()
        start = time.time()
        rs = myq.pop()
        end = time.time()
        print("用了", end - start, '秒')
        return Response({'data': rs, 'time': end - start})


qx = 1


class YzView(APIView):
    def get(self, request):
        # 返回结果中间件中结果
        return Response({'data': qx == request.level})

    def put(self, request):
        global qx
        qx = int(not qx)
        print(qx)
        return Response({'msg': '已修改'})


from my.settings import CLIENT_ID, CLIENT_SECRET, APPLD, APP_SECRET


class Gitee(View):
    def get(self, request):
        return redirect(
            "https://gitee.com/oauth/authorize?client_id=" + CLIENT_ID + "&redirect_uri=http://127.0.0.1:8000/gitee_back&response_type=code")


class GiteeBack(APIView):

    def get(self, request):

        code = request.GET.get("code", None)

        r = requests.post(
            "https://gitee.com/oauth/token?grant_type=authorization_code&code=" + code + "&client_id=" + CLIENT_ID + "&redirect_uri=http://127.0.0.1:8000/gitee_back&client_secret=" + CLIENT_SECRET)
        # print(r.text)
        mess = eval(r.text)
        # print(type(mess))
        # print(mess['access_token'])
        r = requests.get("https://gitee.com/api/v5/user?access_token=" + mess['access_token'])
        print(r.text)
        res = json.loads(r.text)
        user = User.objects.filter(sf_type='0b001', sf_id=res['id']).first()
        if user:
            user.username = res['name']
            user.save()
        else:
            User.objects.create(username=res['name'], sf_type='0b001', sf_id=res['id'], password=res['name'],
                                sf=True)
        return redirect('http://127.0.0.1:8080/#/?username={}'.format(res['name']))


# class DingDing(APIView):
#     # 拼接url
#     # 构造钉钉登录url
#     def get(self,request):
#         appid = APPLD   # 应用中的appid
#         redirect_uri = 'http://127.0.0.1:8000/dingding_back'  #钉钉返回信息的回调地址
#
#         return redirect('https://oapi.dingtalk.com/connect/qrconnect?appid=' + appid + '&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=' + redirect_uri)


import hmac
import base64
from hashlib import sha256
import urllib


class DingBack(View):
    def get(self, request):
        # 获取code
        code = request.GET.get("code")

        t = time.time()
        # 时间戳
        timestamp = str((int(round(t * 1000))))
        appSecret = APP_SECRET
        # 构造签名
        signature = base64.b64encode(
            hmac.new(appSecret.encode('utf-8'), timestamp.encode('utf-8'), digestmod=sha256).digest())
        # 请求接口，换取钉钉用户名
        payload = {'tmp_auth_code': code}
        headers = {'Content-Type': 'application/json'}
        res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature=' + urllib.parse.quote(
            signature.decode("utf-8")) + "&timestamp=" + timestamp + "&accessKey=dingoausbsbnopkbfhhqvt",
                            data=json.dumps(payload), headers=headers)

        res_dict = json.loads(res.text)['user_info']
        print(res_dict['nick'])
        user = User.objects.filter(sf_type='0b010', username=res_dict['nick']).first()
        if user:
            user.username = res_dict['nick']
            user.save()
        else:
            User.objects.create(username=res_dict['nick'], sf_type='0b010', password=res_dict['nick'], sf=True)
            return redirect('http://127.0.0.1:8080/#/?username={}'.format(res_dict['nick']))


def ca(pid):
    # 查询工单里所有与当前审批人对于的数据
    queryset = Gongdan.objects.filter(pid=pid)
    data = GongdanSer(queryset, many=True).data
    # 定义新列表
    lis = []
    # 循环查询到的数据
    for i in data:
        #利用递归无线查询id
        i['x'] = ca(i['id'])
        # 添加到列表中
        lis.append(i)
    # 返回列表
    return lis


class GongdanView(APIView):
    def post(self, request):
        name = request.data.get('name')
        pid = request.data.get('pid')
        #当前审批人是否存在
        if pid:
            Gongdan.objects.create(name=name, pid=pid)
        else:
            Gongdan.objects.create(name=name)

        return Response({'msg': '添加成功'})

    def get(self, request):
        # 查询工单所有数据
        queryset = Gongdan.objects.all()
        all = GongdanSer(queryset, many=True).data
        return Response({"next": ca(0), 'all': all})


class QingJiaView(APIView):
    def get(self, request):
        pid = request.GET.get('pid')
        # 查询当前审核人的数据
        query = Moban.objects(pid=pid).first()
        # 返回mb去接收前段数据，mbs为已有的数据
        return Response({'mb': eval(query.geshi), 'mbs': eval(query.geshi)})

    def put(self, request): # 添加
        pid = request.data.get('pid')
        geshi = request.data.get('geshi')
        # 模板添加当前审核人和格式数据
        Moban.objects.create(pid=pid, geshi=geshi)
        return Response('ok')

    def post(self, request): #修改
        uid = request.data.get('uid')
        # 获取所有审核人
        Approved_list = request.data.get('Approved_list')
        # 判断所有审核人类型如果为int则转换成列表字符串形式
        # if type(eval(Approved_list)) == int:
        #     Approved_list = str([Approved_list])
        qiniuimg = request.data.get('qiniuimg')
        info = request.data.get('info')

        data = QinjiaMoban.objects.create(uid=uid, pid=eval(Approved_list)[0], Approved_list=str(Approved_list), info=str(info),qiniuimg=qiniuimg)

        App = eval(Approved_list)
        if type(App[0])==list:
            for i in App[0]:
                Qingjia_gl.objects.create(gid=data.id,pid=i)
        else:
            Qingjia_gl.objects.create(gid=data.id,pid=App[0])

        return Response({'data': 'ok'})

class Factory:
    def __init__(self,gid,start):
        self.qingjia = QinjiaMoban.objects.filter(id=gid)
        self.qingjia_info = self.qingjia.first()
        self.pid = eval(self.qingjia_info.pid)
        # 关联外键gid
        self.gid = gid
        # 状态
        self.start = start

    # 串审
    def Chuan(self,start):
        # 判断状态不是拒绝时
        if start!=2:
            # 清空当前申请信息
            Qingjia_gl.objects.filter(gid=self.gid).delete()
            # 新建申请信息
            Qingjia_gl.objects.create(gid=self.gid,pid=self.pid)
            self.qingjia.update(pid=str(self.pid),start=3)
        else:
            # 清空当前申请信息
            Qingjia_gl.objects.filter(gid=self.gid).delete()
            Qingjia_gl.objects.create(gid=self.gid,pid=self.pid)
            self.qingjia.update(pid=str(self.pid),start=2)

    # 并审
    def Bing(self,start):
        if start!=2:
            # 清空当前申请信息
            Qingjia_gl.objects.filter(gid=self.gid).delete()
            for i in self.pid:
                # 新建申请信息
                Qingjia_gl.objects.create(gid=self.gid,pid=i)
            self.qingjia.update(pid=self.pid,start=3)
        else:
            # 清空当前申请信息
            Qingjia_gl.objects.filter(gid=self.gid).delete()
            for i in self.pid:
                # 新建申请信息
                Qingjia_gl.objects.create(gid=self.gid,pid=i)
            self.qingjia.update(pid=self.pid,start=2)
    def Zs(self):
        # 执行审批逻辑
        #根据值获取下标
        next_index = eval(self.qingjia_info.Approved_list).index(self.pid)
        # 判断状态不是拒绝时
        if self.start!=2:
            # 审核人列表下标加1
            next_index += 1
            # 如果审核人为最后一个人的时候同意修改pid为None状态为同意
            if next_index == len(eval(self.qingjia_info.Approved_list)):
                self.qingjia.update(pid=None,start=1)
                Qingjia_gl.objects.filter(gid=self.gid).delete()
                # 结束判断
                return
            # 根据获取的下标获取值
            next_pid = eval(self.qingjia_info.Approved_list)[next_index]
            print('pid',next_pid)
            # 修改当前审核人为获取的下标值
            self.qingjia.update(pid=next_pid,start=3)
            self.pid = next_pid
            if type(next_pid)==list:
                self.Bing(self.start)
            else:
                self.Chuan(self.start)
        else:
            if next_index == 0:
                self.qingjia.update(pid=None,start=2)
                Qingjia_gl.objects.filter(gid=self.qingjia_info.id).delete()
                return
            next_index -=1
            next_pid = eval(self.qingjia_info.Approved_list)[next_index]
            self.qingjia.update(pid=next_pid,start=3)
            self.pid = next_pid
            if type(next_pid)==list:
                self.Bing(self.start)
            else:
                self.Chuan(self.start)



class QingjiaZhanshi(APIView):
    def get(self, request):
        uid = request.GET.get('uid')
        # 获取请假模板uid对应的数据
        queryset = QinjiaMoban.objects.filter(uid=uid)
        # 字典返回值
        zs = {0: '未审批', 1: '审批通过', 2: '审批未通过',3: '审批中'}
        data = []
        for i in queryset:
            # 查询User表返回username
            user_info = User.objects.get(id=i.uid)
            js = {}
            # 申请人
            js['username'] = user_info.username
            # 审批人列表
            js['Approved_list'] = []
            # 状态是否审批
            js['start'] = zs[i.start]
            # 凭证图片
            js['qiniuimg'] = i.qiniuimg
            # 对应请假日期原因等
            js['info'] = eval(i.info)
            #循环查询数据中的审批人列表
            for j in eval(i.Approved_list):
                # 如果审批人的类型为list
                if type(j)==list:
                    # 审批人展示
                    js['Approved_list'].append(
                        [User.objects.get(id=k).username for k in j]
                    )
                else:
                    js['Approved_list'].append(User.objects.get(id=j).username)
            # 如果当然审批人存在
            if i.pid:
                e_pid = eval(i.pid)
                # 如果当然审批人的类型为list
                if type(e_pid) == list:
                    # 当前审批人姓名添加列表
                    js['pid_name'] = [User.objects.get(id=k).username for k in e_pid]
                # 如果类型不为list
                else:
                    #当前单个审批人添加列表
                    js['pid_name'] = User.objects.get(id=e_pid).username
                # 根据值查询下标赋值
                js['f_index'] = js['Approved_list'].index(js['pid_name'])
            else:
                js['f_index'] = None
            #如果状态为审批未通过
            if i.start == 2:
                # 拒绝原因修改赋值
                js['refuse'] = i.refuse
            else:
                # 否则为None
                js['refuse'] = None
            # 循环的数据添加到列表
            data.append(js)

        return Response(data)

    def put(self, request):
        # 获取请假模板的id查询
        id = request.data.get('id')
        # 审批为通过拒绝1为通过2为拒绝
        start = request.data.get('start')
        # 审批拒绝原因
        refuse = request.data.get('refuse', None)
        # 查询请假模板对应id的数据
        qingjia = QinjiaMoban.objects.filter(id=id)
        # qingjia_info = qingjia.first()
        # 如果拒绝原因存在
        if refuse:
            # 则修改拒绝原因
            qingjia.update(refuse=refuse)
        ccs =Factory(gid=id,start=start)
        ccs.Zs()
        # 如果状态不为拒绝(2)
        # if start != 2:
        #     # 赋值pid转换类型
        #     pid = eval(qingjia_info.pid)
        #     # a_list定义的列表转换Approved_list为list的类型
        #     a_list = eval(qingjia_info.Approved_list)
        #     # 当前下标的下标+1为当前审核人的下标
        #     next_index = a_list.index(pid) + 1
        #     # 如果当前下标+1后的长度等于最后一个值的时候
        #     if next_index == len(a_list):
        #         # 修改状态为审核通过
        #         qingjia.update(start=1)
        #         # 当前审核人为空
        #         qingjia.update(pid=None)
        #     else:
        #         # 如果不为最后一个值的时候状态为正在审核中
        #         qingjia.update(start=3)
        #         # 修改pid的值为当前审核人的下标
        #         qingjia.update(pid=a_list[next_index])
        # else:
        #     pid = qingjia_info.pid
        #     # 赋值a_list为转换为后的审核人列表(list)
        #     a_list = eval(qingjia_info.Approved_list)
        #     # pid_index当前审核人下标
        #     pid_index = a_list.index(eval(pid))
        #     # 如果下标为0拒绝
        #     if pid_index == 0:
        #         # 赋值pid为空
        #         qingjia.update(pid=None)
        #         # 状态为审核未通过
        #         qingjia.update(start=2)
        #     else:
        #         # 如果下标不为0拒绝则回退下标减1
        #         qingjia.update(pid=a_list[pid_index - 1])
        #         # 修改状态为审核中
        #         qingjia.update(start=3)

        return Response({'msg': '审批完成'})

    def post(self, request):
        pid = request.data.get('pid')

        query = Qingjia_gl.objects.filter(pid=pid)

        data = [QingJiaInfoSer(i.gid) for i in query]
        # # 获取当前审核人pid
        # pid = request.data.get('pid')
        # # 获取全部数据
        # query = QinjiaMoban.objects.all()
        # # 定义空列表
        # data = []
        # zs = {0: '未审批', 1: '审批通过', 2: '审批未通过',3: '审批中'}
        # # 循环query数据
        # for i in query:
        #     # 如果当前审核人存在
        #     if i.pid:
        #         # 转换赋值
        #         i_pid = eval(i.pid)
        #     else:
        #         #跳过当前循环继续下一次循环
        #         continue
        #     # 如果赋值的pid类型为list
        #     if type(i_pid)==list:
        #         #又如果pid在在列表中
        #         if not pid in eval(i.pid):
        #             # 跳过当前循环继续下一次循环
        #             continue
        #     # if not i.pid == i_pid:
        #     #     continue
        #     # 查询User表返回username
        #     user_info = User.objects.get(id=i.uid)
        #     js = {}
        #     js['id'] = i.id
        #     js['name'] = user_info.username
        #     js['start'] = zs[i.start]
        #     js['info'] = eval(i.info)
        #
        #     data.append(js)

        return Response(data)


from qiniu import Auth
from my.settings import AccessKey, SecretKey


def qiniu_token():
    # 定义密钥
    qn = Auth('c6WPZAJYWKjtl-A0d9lnx0NeHpXtVUnPFKPM1er5', 'fVGVpKAjM2PHUaEoQ5EnDcO6krasp95rRGFJMrFZ')
    # 指定上传空间, 返回token值
    token = qn.upload_token('sbzjj')
    return token


from django.views import View
from django.http import JsonResponse


class UpTokenView(View):

    def get(self, request):

        return JsonResponse({'token': qiniu_token()})


import upyun


# 定义文件上传类
class UploadFile(View):
    # 又拍云
    def post(self,request):

        up = upyun.UpYun('admin-cat', 'gaolei', 'Ji2h1CtsohhAyPsVn1F6eZ85i5htEoGc')

        headers = {'x-gmkerl-thumb': '/fw/300'}

        with up as f:
            res = up.put('/4.jpg', f, checksum=True, headers=headers)
        return Response({'data': 'ok'})

class Message(APIView):

    def get(self,request):

        pid = request.GET.get('pid') #当前审核人id

        start = request.GET.get('start') #当前状态

        mess = QinjiaMoban.objects.filter(pid=pid,start=start).count()

        return Response(mess)

















